1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 package com.sun.media.sound;
26
27 import java.io.IOException;
28 import java.util.Arrays;
29
30 import javax.sound.midi.MidiChannel;
31 import javax.sound.midi.VoiceStatus;
32
33
34
35
36
37
38 public abstract class SoftAbstractResampler implements SoftResampler {
39
40 private class ModelAbstractResamplerStream implements SoftResamplerStreamer {
41
42 AudioFloatInputStream stream;
43 boolean stream_eof = false;
44 int loopmode;
45 boolean loopdirection = true;
46 float loopstart;
47 float looplen;
48 float target_pitch;
49 float[] current_pitch = new float[1];
50 boolean started;
51 boolean eof;
52 int sector_pos = 0;
53 int sector_size = 400;
54 int sector_loopstart = -1;
55 boolean markset = false;
56 int marklimit = 0;
57 int streampos = 0;
58 int nrofchannels = 2;
59 boolean noteOff_flag = false;
60 float[][] ibuffer;
61 boolean ibuffer_order = true;
62 float[] sbuffer;
63 int pad;
64 int pad2;
65 float[] ix = new float[1];
66 int[] ox = new int[1];
67 float samplerateconv = 1;
68 float pitchcorrection = 0;
69
70 public ModelAbstractResamplerStream() {
71 pad = getPadding();
72 pad2 = getPadding() * 2;
73 ibuffer = new float[2][sector_size + pad2];
74 ibuffer_order = true;
75 }
76
77 public void noteOn(MidiChannel channel, VoiceStatus voice,
78 int noteNumber, int velocity) {
79 }
80
81 public void noteOff(int velocity) {
82 noteOff_flag = true;
83 }
84
85 public void open(ModelWavetable osc, float outputsamplerate)
86 throws IOException {
87
88 eof = false;
89 nrofchannels = osc.getChannels();
90 if (ibuffer.length < nrofchannels) {
91 ibuffer = new float[nrofchannels][sector_size + pad2];
92 }
93
94 stream = osc.openStream();
95 streampos = 0;
96 stream_eof = false;
97 pitchcorrection = osc.getPitchcorrection();
98 samplerateconv
99 = stream.getFormat().getSampleRate() / outputsamplerate;
100 looplen = osc.getLoopLength();
101 loopstart = osc.getLoopStart();
102 sector_loopstart = (int) (loopstart / sector_size);
103 sector_loopstart = sector_loopstart - 1;
104
105 sector_pos = 0;
106
107 if (sector_loopstart < 0)
108 sector_loopstart = 0;
109 started = false;
110 loopmode = osc.getLoopType();
111
112 if (loopmode != 0) {
113 markset = false;
114 marklimit = nrofchannels * (int) (looplen + pad2 + 1);
115 } else
116 markset = true;
117
118
119 target_pitch = samplerateconv;
120 current_pitch[0] = samplerateconv;
121
122 ibuffer_order = true;
123 loopdirection = true;
124 noteOff_flag = false;
125
126 for (int i = 0; i < nrofchannels; i++)
127 Arrays.fill(ibuffer[i], sector_size, sector_size + pad2, 0);
128 ix[0] = pad;
129 eof = false;
130
131 ix[0] = sector_size + pad;
132 sector_pos = -1;
133 streampos = -sector_size;
134
135 nextBuffer();
136 }
137
138 public void setPitch(float pitch) {
139
140
141
142
143
144 this.target_pitch = (float)Math.exp(
145 (pitchcorrection + pitch) * (Math.log(2.0) / 1200.0))
146 * samplerateconv;
147
148 if (!started)
149 current_pitch[0] = this.target_pitch;
150 }
151
152 public void nextBuffer() throws IOException {
153 if (ix[0] < pad) {
154 if (markset) {
155
156 stream.reset();
157 ix[0] += streampos - (sector_loopstart * sector_size);
158 sector_pos = sector_loopstart;
159 streampos = sector_pos * sector_size;
160
161
162 ix[0] += sector_size;
163 sector_pos -= 1;
164 streampos -= sector_size;
165 stream_eof = false;
166 }
167 }
168
169 if (ix[0] >= sector_size + pad) {
170 if (stream_eof) {
171 eof = true;
172 return;
173 }
174 }
175
176 if (ix[0] >= sector_size * 4 + pad) {
177 int skips = (int)((ix[0] - sector_size * 4 + pad) / sector_size);
178 ix[0] -= sector_size * skips;
179 sector_pos += skips;
180 streampos += sector_size * skips;
181 stream.skip(sector_size * skips);
182 }
183
184 while (ix[0] >= sector_size + pad) {
185 if (!markset) {
186 if (sector_pos + 1 == sector_loopstart) {
187 stream.mark(marklimit);
188 markset = true;
189 }
190 }
191 ix[0] -= sector_size;
192 sector_pos++;
193 streampos += sector_size;
194
195 for (int c = 0; c < nrofchannels; c++) {
196 float[] cbuffer = ibuffer[c];
197 for (int i = 0; i < pad2; i++)
198 cbuffer[i] = cbuffer[i + sector_size];
199 }
200
201 int ret;
202 if (nrofchannels == 1)
203 ret = stream.read(ibuffer[0], pad2, sector_size);
204 else {
205 int slen = sector_size * nrofchannels;
206 if (sbuffer == null || sbuffer.length < slen)
207 sbuffer = new float[slen];
208 int sret = stream.read(sbuffer, 0, slen);
209 if (sret == -1)
210 ret = -1;
211 else {
212 ret = sret / nrofchannels;
213 for (int i = 0; i < nrofchannels; i++) {
214 float[] buff = ibuffer[i];
215 int ix = i;
216 int ix_step = nrofchannels;
217 int ox = pad2;
218 for (int j = 0; j < ret; j++, ix += ix_step, ox++)
219 buff[ox] = sbuffer[ix];
220 }
221 }
222
223 }
224
225 if (ret == -1) {
226 ret = 0;
227 stream_eof = true;
228 for (int i = 0; i < nrofchannels; i++)
229 Arrays.fill(ibuffer[i], pad2, pad2 + sector_size, 0f);
230 return;
231 }
232 if (ret != sector_size) {
233 for (int i = 0; i < nrofchannels; i++)
234 Arrays.fill(ibuffer[i], pad2 + ret, pad2 + sector_size, 0f);
235 }
236
237 ibuffer_order = true;
238
239 }
240
241 }
242
243 public void reverseBuffers() {
244 ibuffer_order = !ibuffer_order;
245 for (int c = 0; c < nrofchannels; c++) {
246 float[] cbuff = ibuffer[c];
247 int len = cbuff.length - 1;
248 int len2 = cbuff.length / 2;
249 for (int i = 0; i < len2; i++) {
250 float x = cbuff[i];
251 cbuff[i] = cbuff[len - i];
252 cbuff[len - i] = x;
253 }
254 }
255 }
256
257 public int read(float[][] buffer, int offset, int len)
258 throws IOException {
259
260 if (eof)
261 return -1;
262
263 if (noteOff_flag)
264 if ((loopmode & 2) != 0)
265 if (loopdirection)
266 loopmode = 0;
267
268
269 float pitchstep = (target_pitch - current_pitch[0]) / len;
270 float[] current_pitch = this.current_pitch;
271 started = true;
272
273 int[] ox = this.ox;
274 ox[0] = offset;
275 int ox_end = len + offset;
276
277 float ixend = sector_size + pad;
278 if (!loopdirection)
279 ixend = pad;
280 while (ox[0] != ox_end) {
281 nextBuffer();
282 if (!loopdirection) {
283
284
285
286 if (streampos < (loopstart + pad)) {
287 ixend = loopstart - streampos + pad2;
288 if (ix[0] <= ixend) {
289 if ((loopmode & 4) != 0) {
290
291 loopdirection = true;
292 ixend = sector_size + pad;
293 continue;
294 }
295
296 ix[0] += looplen;
297 ixend = pad;
298 continue;
299 }
300 }
301
302 if (ibuffer_order != loopdirection)
303 reverseBuffers();
304
305 ix[0] = (sector_size + pad2) - ix[0];
306 ixend = (sector_size + pad2) - ixend;
307 ixend++;
308
309 float bak_ix = ix[0];
310 int bak_ox = ox[0];
311 float bak_pitch = current_pitch[0];
312 for (int i = 0; i < nrofchannels; i++) {
313 if (buffer[i] != null) {
314 ix[0] = bak_ix;
315 ox[0] = bak_ox;
316 current_pitch[0] = bak_pitch;
317 interpolate(ibuffer[i], ix, ixend, current_pitch,
318 pitchstep, buffer[i], ox, ox_end);
319 }
320 }
321
322 ix[0] = (sector_size + pad2) - ix[0];
323 ixend--;
324 ixend = (sector_size + pad2) - ixend;
325
326 if (eof) {
327 current_pitch[0] = this.target_pitch;
328 return ox[0] - offset;
329 }
330
331 continue;
332 }
333 if (loopmode != 0) {
334 if (streampos + sector_size > (looplen + loopstart + pad)) {
335 ixend = loopstart + looplen - streampos + pad2;
336 if (ix[0] >= ixend) {
337 if ((loopmode & 4) != 0 || (loopmode & 8) != 0) {
338
339 loopdirection = false;
340 ixend = pad;
341 continue;
342 }
343 ixend = sector_size + pad;
344 ix[0] -= looplen;
345 continue;
346 }
347 }
348 }
349
350 if (ibuffer_order != loopdirection)
351 reverseBuffers();
352
353 float bak_ix = ix[0];
354 int bak_ox = ox[0];
355 float bak_pitch = current_pitch[0];
356 for (int i = 0; i < nrofchannels; i++) {
357 if (buffer[i] != null) {
358 ix[0] = bak_ix;
359 ox[0] = bak_ox;
360 current_pitch[0] = bak_pitch;
361 interpolate(ibuffer[i], ix, ixend, current_pitch,
362 pitchstep, buffer[i], ox, ox_end);
363 }
364 }
365
366 if (eof) {
367 current_pitch[0] = this.target_pitch;
368 return ox[0] - offset;
369 }
370 }
371
372 current_pitch[0] = this.target_pitch;
373 return len;
374 }
375
376 public void close() throws IOException {
377 stream.close();
378 }
379 }
380
381 public abstract int getPadding();
382
383 public abstract void interpolate(float[] in, float[] in_offset,
384 float in_end, float[] pitch, float pitchstep, float[] out,
385 int[] out_offset, int out_end);
386
387 public SoftResamplerStreamer openStreamer() {
388 return new ModelAbstractResamplerStream();
389 }
390 }